增加抽奖活动

FFIB 11 часов назад
Родитель
Сommit
e67d02ba23
3 измененных файлов с 77 добавлено и 0 удалено
  1. 71 0
      api/sale/lottery_views.py
  2. 1 0
      api/sale/urls.py
  3. 5 0
      utils/error/errno_utils.py

+ 71 - 0
api/sale/lottery_views.py

@@ -1 +1,72 @@
1
+# -*- coding: utf-8 -*-
1 2
 
3
+from django.db import IntegrityError, transaction
4
+from django.utils import timezone
5
+from django_logit import logit
6
+from django_response import response
7
+from django.db.models import Q
8
+
9
+from account.models import UserInfo
10
+from sales.models import LotteryCampaignInfo, LotteryEntryInfo
11
+from utils.error.errno_utils import LotteryStatusCode, UserStatusCode
12
+
13
+def join_lottery(user, serial_no, model_id='', campaign_id='', submit_pk='', phone='', model_name=''):
14
+    """
15
+    写入抽奖名额(幂等)
16
+
17
+    返回 (entry, campaign, is_new):
18
+      · 没有进行中的活动 → (None, None, False)
19
+      · 已有名额         → (entry, campaign, False)
20
+      · 首次参与         → (entry, campaign, True)
21
+    """
22
+    serial_no = (serial_no or '').strip()
23
+
24
+    campaign = LotteryCampaignInfo.objects.get(status=True, campaign_id=campaign_id)
25
+
26
+    if not campaign:
27
+        return None, None
28
+
29
+    # 嵌套 atomic 生成 savepoint:并发插入冲突后还能继续查询
30
+    with transaction.atomic():
31
+        entry, created = LotteryEntryInfo.objects.get_or_create(
32
+            campaign_id=campaign.campaign_id,
33
+            serial_no=serial_no,
34
+            submit_pk=submit_pk,
35
+            title=campaign.title,
36
+            phone=phone,
37
+            user_id=user.user_id,
38
+            model_id=model_id,
39
+            model_name=model_name,
40
+        )
41
+
42
+    return entry, campaign
43
+
44
+
45
+@logit(res=True)
46
+@transaction.atomic
47
+def lottery_join_api(request):
48
+    """抽奖参与接口:写入名额"""
49
+    user_id = request.POST.get('user_id', '')
50
+    serial_no = request.POST.get('serial_no')
51
+    model_id = request.POST.get('model_id')
52
+    campaign_id = request.POST.get('campaign_id', '')
53
+    submit_pk = request.POST.get('submit_pk', '')
54
+    phone = request.POST.get('phone', '')
55
+    model_name = request.POST.get('model_name', '')
56
+
57
+    try:
58
+        user = UserInfo.objects.select_for_update().get(user_id=user_id)
59
+    except UserInfo.DoesNotExist:
60
+        return response(UserStatusCode.USER_NOT_FOUND)
61
+
62
+    # TODO 安全:应校验该序列号确实绑定在当前用户名下,防止传入他人序列号刷名额
63
+
64
+    entry, campaign = join_lottery(user, serial_no, model_id, campaign_id, submit_pk, phone, model_name)
65
+
66
+    if not campaign:
67
+        return response(LotteryStatusCode.CAMPAIGN_NOT_FOUND)
68
+
69
+    return response(200, data={
70
+        'campaign': serialize_campaign(campaign),
71
+        'entry': serialize_entry(entry),
72
+    })

+ 1 - 0
api/sale/urls.py

@@ -5,4 +5,5 @@ from django.conf.urls import include, url
5 5
 from api.sale import lottery_views
6 6
 
7 7
 urlpatterns = [
8
+    url(r'^sale/lottery/join$', lottery_views.lottery_join_api, name='lottery_join_api'),
8 9
 ]

+ 5 - 0
utils/error/errno_utils.py

@@ -234,3 +234,8 @@ class ContractStatusCode(BaseStatusCode):
234 234
 class TencentCloudStatusCode(BaseStatusCode):
235 235
     """ 腾讯云SDK错误码 5099xx """
236 236
     TENCENT_CLOUD_SDK_EXCEPTION = StatusCodeField(509901, 'Tencent Cloud SDK Exception', description=u'腾讯云SDK报错')
237
+
238
+
239
+class LotteryStatusCode(BaseStatusCode):
240
+    """ 抽奖相关错误码 5099xx """
241
+    CAMPAIGN_NOT_FOUND = StatusCodeField(509902, 'Campaign Not Found', description=u'抽奖活动不存在')